﻿using System;
using System.IO.Ports;
using TYBase;

namespace TYRTUBase {

    public delegate void DelegateOnComDataSend(ITYClient sender, byte[] data);

    public delegate void DelegateOnComDataRead(ITYClient sender, byte[] data);

    public delegate void DelegateOnCom_Close_Connected(ITYClient sender, bool isConnected);

    public class DeviceBase {
        public bool IsSysRtu { get; set; } = false;
        public bool IsTCP { get; set; } = false;
        public event DelegateOnComDataSend OnComDataSend;

        public event DelegateOnComDataRead OnComDataRead;

        public event DelegateOnCom_Close_Connected OnCom_Close_Connected;

        public byte[] LastSendData = null;

        internal byte[] ToCmdByte(string cmd) {
            return cmd.AsBytes().Append(NewLine);
        }



        public static ScanerPara DefaultPara = new ScanerPara() {
            baudRate = 9600,
            parity = System.IO.Ports.Parity.None,
            dataBits = 8,
            stopBits = System.IO.Ports.StopBits.One
        };

        public string EquipId { get; private set; }
        public string EquipName { get; private set; }

        public EnumEquipType EquipType { get; private set; } = EnumEquipType.Scaner;

        public DeviceBase(EnumEquipType equipType,
            string equipId, string equipName, bool isSysRtu = false, bool isTcp = false) {
            IsSysRtu = isSysRtu;
            IsTCP = isTcp;
            EquipId = equipId;
            EquipType = equipType;
            EquipName = equipName;
        }

        public void SetIsXMode(bool v) {
            IsXModerMode = v;
        }

        internal static Random _rand = new Random();

        /// <summary>
        /// 是否是模拟数据模式
        /// </summary>
        internal bool IsXModerMode = false;

        public ITYClient rtu = null;
        internal int ReadOutTime = 5000;
        internal byte[] NewLine = new byte[] { 0x0D, 0x0A };
        public bool IsRun = true;
        public int Com {
            get {
                if (para != null) {
                    return para.Com;
                }
                return 0;
            }
        }

        internal int repeatTime = 3;
        private bool isConnected = false;

        public void SetNewLine(byte[] newLine) {
            if (newLine != null) {
                NewLine = newLine;
            }
        }

        public ScanerPara para { get; set; }

        public virtual void SetPara(ScanerPara _para) {
            para = _para;
        }

        public virtual void Init() {            
            if (para != null) {
                if (IsTCP) {
                    rtu = (new TYTCP(para.IP, para.Port));
                }
                else {
                    if (IsSysRtu) {
                        rtu = (new TYSysRTU(para.Com, para));
                    }
                    else {
                        rtu = (new TYRTUPComm(para.Com, para));
                    }
                }
                SetNewLine(para.NewLine);
            }
            else {

                if (IsSysRtu) {
                    rtu = (new TYSysRTU(para.Com, DefaultPara));
                }
                else {
                    rtu = (new TYRTUPComm(para.Com, DefaultPara));
                }
                SetNewLine(DefaultPara.NewLine);
            }
            rtu.OnComDataRead += Rtu_OnComDataRead;
            rtu.OnComDataSend += Rtu_OnComDataSend;
        }



        private void Rtu_OnComDataSend(ITYClient com, byte[] data) {
            OnComDataSend?.Invoke(com, data);
        }

        private void Rtu_OnComDataRead(ITYClient com, byte[] data) {
            OnComDataRead?.Invoke(com, data);
        }

        public bool IsConnected {
            get => isConnected; private set {
                var preConn = isConnected;
                isConnected = value;
                if (preConn != value) {
                    OnCom_Close_Connected?.Invoke(rtu, value);
                }
            }
        }

        public bool Connect() {
            if (IsXModerMode) {
                IsConnected = true;
                return IsConnected;
            }
            if (rtu != null) {
                IsConnected = rtu.Connect();
            }
            return IsConnected;
        }

        public void Dispose() {
            IsRun = false;
        }

        public bool CheckComOK() {
            if (IsXModerMode)
                return true;
            if (rtu == null) {
                Log.I($"串口为空 :{Com}");
                return false;
            }
            if (!rtu.IsConnected) {
                Log.I($"串口未连接 :{Com}");
                return false;
            }
            return true;
        }

        public bool Close() {
            IsConnected = false;
            if (IsXModerMode)
                return true;
            if (rtu == null)
                return false;
            rtu.Close();
            return true;
        }

        public bool Read(out byte[] data) {
            if (!CheckComOK()) {
                data = null;
                return false;
            }
            if (rtu.Read(out data) > 0) {
                return true;
            }
            return false;
        }

        public void Init(int com) {
            para.Com = com;
            Init();
        }
    }
}